package com.zeny.online.netty;

import com.zeny.online.common.MsgActionEnum;
import com.zeny.online.common.MsgSignFlagEnum;
import com.zeny.online.entity.vo.MyFriendVO;
import com.zeny.online.service.ChatMsgService;
import com.zeny.online.service.impl.MyFriendsServiceImpl;
import com.zeny.online.util.JsonUtils;
import com.zeny.online.util.SpringUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.annotation.Id;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @ClassName ChatHandler
 * @Description TODO
 * @Author zeny
 */
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    //用于记录client
    public static final ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
//        String content = msg.text();
//        System.out.println("接收到的数据: "  + content);
//        for (Channel channel : clients) {
//            channel.writeAndFlush(new TextWebSocketFrame("[服务器在]" + LocalDateTime.now() + "接收到消息, 消息为: " + content));
//        }

        Channel currentChannel = ctx.channel();
        //1、获取客户端发来的消息data
        String content = msg.text();
        DataContent dataContent = JsonUtils.jsonToPojo(content, DataContent.class);
        //2、判断消息类型，根据不同的类型处理不同的业务
        Integer action = dataContent.getAction();
        if (MsgActionEnum.CONNECT.type.equals(action)) {
            //2.1 、当websocket 第一次open的时候，初始化channel，把能用的channel和userID关联起来
            String senderId = dataContent.getChatMsg().getSenderId();
            UserChannelRel.put(senderId, currentChannel);

            //测试
            for (Channel client : clients) {
                System.out.println(client + " : " +client.id().asLongText());
            }
            UserChannelRel.output();

        } else if (MsgActionEnum.CHAT.type.equals(action)) {
            //2.2 、聊天类型的消息，把聊天记录保存到数据库，同时标记消息的签收状态【未签收】
            ChatMsg chatMsg = dataContent.getChatMsg();
            String msgText = chatMsg.getMsg();
            String receiverId = chatMsg.getReceiverId();
            String senderId = chatMsg.getSenderId();
            //保存到数据库，同时标记消息的签收状态【未签收】
            ChatMsgService chatMsgService = (ChatMsgService) SpringUtil.getBean("chatMsgServiceImpl");
            com.zeny.online.entity.ChatMsg chatMsgEntity = new com.zeny.online.entity.ChatMsg();
            chatMsgEntity.setSendUserId(senderId);
            chatMsgEntity.setAcceptUserId(receiverId);
            chatMsgEntity.setMsg(msgText);
            chatMsgEntity.setCreateTime(new Date());
            chatMsgEntity.setSignFlag(MsgSignFlagEnum.unsign.type);
            chatMsgService.save(chatMsgEntity);
            //保存成功后获得的消息ID封装到chatMsg中，一起发送给接受方
            chatMsg.setMsgId(chatMsgEntity.getId());
            //发送消息到接受方
            Channel receiverChannel = UserChannelRel.get(receiverId);
            if (receiverChannel == null) {
                //TODO channel 为空代表用户离线，推送消息（jpush,个推,小米推送）
            }else {
                Channel findChannel = clients.find(receiverChannel.id());
                if (findChannel != null) {
                    //用户在线
                    DataContent response = new DataContent();
                    response.setAction(dataContent.getAction());
                    response.setChatMsg(chatMsg);
                    receiverChannel.writeAndFlush(new TextWebSocketFrame(JsonUtils.objectToJson(response)));
                } else {
                    //TODO channel 为空代表用户离线，推送消息（jpush,个推,小米推送）
                }
            }
        } else if (MsgActionEnum.SIGNED.type.equals(action)) {
            //2.3 、签收消息类型，针对你具体的消息进行签收，修改数据库中对应的签收状态【已签收】
            ChatMsgService chatMsgService = (ChatMsgService) SpringUtil.getBean("chatMsgServiceImpl");
            //扩展字段在signed类型的消息中，代表需要去签收的消息ID，逗号分隔
            String contentExtand = dataContent.getExtand();
            if (StringUtils.isBlank(contentExtand)) {
                //TODO
            } else {
                String[] msgIds = contentExtand.split(",");
                List<String> ids = Arrays.asList(msgIds);
                //批量签收
                chatMsgService.batchSign(ids);
            }

        } else if (MsgActionEnum.KEEPALIVE.type.equals(action)) {
            //2.4 、心跳类型的消息
            System.out.println("收到来自channel为[" + currentChannel + "]的心跳包...");
        }
    }

    /**
     * @Description 客户端连接服务端
     * @param ctx
     * @return void
     **/
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        clients.add(channel);
    }

    /**
     * @Description //描述
     * @param ctx
     * @return void
     **/
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        clients.remove(ctx.channel());
        System.out.println("客户端断开, channel对应的长ID: " + ctx.channel().id().asLongText());
        System.out.println("客户端断开, channel对应的短ID: " + ctx.channel().id().asShortText());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        //发生异常后关闭连接, 随后从ChannelGroup中移除
        ctx.channel().close();
        clients.remove(ctx.channel());
    }
}
